package com.c3w.synchro.exporter;

import com.c3w.synchro.common.validation.event.DuplicateBeanException;
import com.c3w.synchro.common.validation.event.ValidationFailedException;
import com.c3w.synchro.member.bean.*;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.hibernate.cfg.SetSimpleValueTypeSecondPass;
import org.springframework.stereotype.Repository;

import java.io.*;
import java.util.*;


/**
 * User: magirard
 * Date: 12-10-02
 */
@Repository("excelBeanConverterEngine")
public class ExcelBeanConverterEngine {


    private static final Logger LOGGER = Logger.getLogger(ExcelBeanConverterEngine.class);
    private Workbook wb;
    private Workbook newWb;

    private ArrayList<Athlete> athleteList = new ArrayList<>();
    private ArrayList<Team> figureList = new ArrayList<>();

    // Liste des differentes equipes possibles
    private ArrayList<Club> clubList = new ArrayList<>();
    private ArrayList<Team> figureEquipeList = new ArrayList<>();
    private ArrayList<Team> equipeList = new ArrayList<>();
    private ArrayList<Team> equipeTechList = new ArrayList<>();
    private ArrayList<Team> equipeFreeList = new ArrayList<>();
    private ArrayList<Team> comboList = new ArrayList<>();
    private ArrayList<Coach> coachList = new ArrayList<>();
    private ArrayList<Team> soloList = new ArrayList<>();
    private ArrayList<Team> soloTechList = new ArrayList<>();
    private ArrayList<Team> soloFreeList = new ArrayList<>();
    private ArrayList<Team> duoList = new ArrayList<>();
    private ArrayList<Team> duoTechList = new ArrayList<>();
    private ArrayList<Team> duoFreeList = new ArrayList<>();

    public void openFile(InputStream in) throws IOException, DuplicateBeanException, ValidationFailedException {

        // create a new workbook
        wb = new HSSFWorkbook(in);
        getMember();

    }

    /**
     * Trouve l'ordre dans lequel se trouve les competitions, nom et categorie *
     */
    public void getRowOrder() {
        Sheet sheet = wb.getSheetAt(0);
        int rows = sheet.getPhysicalNumberOfRows();

        Row row = sheet.getRow(0);
        if (row != null) {
            int cells = row.getPhysicalNumberOfCells();

            for (int c = 0; c < cells; c++) {
                Cell cell = row.getCell(c);

                LOGGER.info(cell.toString());
            }
        }
    }

    public long addClubInList(Club club) {
        boolean found = false;

        for (Club inxClub : clubList) {

            if (club.getName().equals(inxClub.getName())) {
                found = true;
                break;
            }
        }

        long Id = clubList.size();

        if (!found) {
            clubList.add(club);
        }

        return club.getId();
    }

    public boolean teamExist(Collection<Team> teamList, String teamName, long clubId, boolean substitute, int age, Athlete athlete) {

        for (Team team : teamList) {
            if (team.getName().equals(teamName) && team.getClubId() == clubId) {

                if (!substitute) {
                    team.addAthlete(athlete);
                }

                team.addToAgeSum(age);

                if (substitute) {
                    team.addSubstitute(athlete);
                }
                return true;
            }
        }

        return false;
    }

    public void fillTeamList(Cell cell,
                             Collection<Team> teamList,
                             long clubId,
                             String teamName,
                             boolean substitute,
                             int age, Athlete athlete, Coach coach) {

        if (cell.getCellType() != Cell.CELL_TYPE_BLANK) {
            boolean addTeam = true;

            if (!teamName.isEmpty()) {
                if (teamExist(teamList, teamName, clubId, substitute, age, athlete)) {
                    addTeam = false;
                }
            }

            if (addTeam) {
                Team team = new Team();
                if (!substitute) {
                    team.addAthlete(athlete);
                }

                team.setClubId(clubId);
                team.setName(teamName);
                team.setCoaches(Arrays.asList(coach));
                team.addToAgeSum(age);
                if (substitute) {
                    team.addSubstitute(athlete);
                }

                teamList.add(team);

            }
        }

    }

    public void getMember() throws DuplicateBeanException, ValidationFailedException {

        Sheet sheet = wb.getSheetAt(0);
        int rows = sheet.getPhysicalNumberOfRows();

        LOGGER.info("Begin conversion...");

        for (int r = 1; r < rows; r++) {

            Row row = sheet.getRow(r);
            if (row == null) {
                continue;
            }

            // creation de l'athlete
            Athlete athlete = new Athlete();
            Cell cell = row.getCell(0);
            athlete.setName(cell.toString());

            // devra savoir pour le genre de l'athlete
            // plus tard. Pour l'instant, on considere
            // que c'est une fille etant donnee qu'elles sont
            // majoritaire dans le sport
            athlete.setGender(Member.Gender.F);

            cell = row.getCell(3);
            athlete.setAge((int) cell.getNumericCellValue());

            // ajoute le club a la liste
            Club club = new Club();
            cell = row.getCell(1);
            club.setName(cell.toString());
            long clubId = addClubInList(club);

            athlete.setClubName(club.getName());
            athleteList.add(athlete);


            Coach coach = null;

            // rempli la liste de figures
            fillTeamList(row.getCell(4), figureList, clubId, "FIGURE", false, athlete.getAge(), athlete, coach);

            // Rempli la liste de solo
            fillTeamList(row.getCell(5), soloList, clubId, "SOLO", false, athlete.getAge(), athlete, coach);

            // Rempli la liste de duo
            boolean substitute = row.getCell(8).getCellType() != Cell.CELL_TYPE_BLANK;
            fillTeamList(row.getCell(7), duoList, clubId, row.getCell(7).toString(), substitute, athlete.getAge(), athlete, coach);

            // rempli la liste de figures
            fillTeamList(row.getCell(10), figureEquipeList, clubId, "EQUIPE", false, athlete.getAge(), athlete, coach);

            // Rempli la liste d'equipe
            substitute = row.getCell(12).getCellType() != Cell.CELL_TYPE_BLANK;
            fillTeamList(row.getCell(11), equipeList, clubId, row.getCell(11).toString(), substitute, athlete.getAge(), athlete, coach);

            // Rempli la liste de combo
            fillTeamList(row.getCell(14), comboList, clubId, row.getCell(14).toString(), false, athlete.getAge(), athlete, coach);

            // remplic la liste de solo technique
            fillTeamList(row.getCell(16), soloTechList, clubId, "SOLOTECH", false, athlete.getAge(), athlete, coach);

            // rempli la liste de solo libre
            fillTeamList(row.getCell(18), soloFreeList, clubId, "SOLOFREE", false, athlete.getAge(), athlete, coach);

            // Rempli la liste de duo technique
            fillTeamList(row.getCell(20), duoTechList, clubId, row.getCell(20).toString(), false, athlete.getAge(), athlete, coach);

            // Rempli la liste de duo libre
            fillTeamList(row.getCell(22), duoFreeList, clubId, row.getCell(22).toString(), false, athlete.getAge(), athlete, coach);

            // Rempli la liste d'equipe technique
            substitute = row.getCell(25).getCellType() != Cell.CELL_TYPE_BLANK;
            fillTeamList(row.getCell(24), equipeTechList, clubId, row.getCell(24).toString(), false, athlete.getAge(), athlete, coach);

            // Rempli la liste d'equipe libre
            substitute = row.getCell(28).getCellType() != Cell.CELL_TYPE_BLANK;
            fillTeamList(row.getCell(27), equipeFreeList, clubId, row.getCell(27).toString(), substitute, athlete.getAge(), athlete, coach);
        }

        LOGGER.info("End conversion...");
    }

    public Collection<Club> getClubList() {

        for (Club club : clubList) {
            LOGGER.info("Club: " + club.getName() + " Id " + club.getId());
        }

        return clubList;

    }

    public Collection<Team> getTeamList(TeamType teamType) {

        int index = 0;

        ArrayList<Team> teamList;

        switch (teamType) {
            case TEAM_PARTICIPATION:
                teamList = equipeList;
                break;

            case TEAM_TECHNICAL:
                teamList = equipeTechList;
                break;

            case TEAM_FREE:
                teamList = equipeFreeList;
                break;

            case FIGURE_SOLO_DUO:
                teamList = figureList;
                break;

            case FIGURE_TEAM:
                teamList = figureEquipeList;
                break;

            case SOLO:
                teamList = soloList;
                break;

            case SOLO_TECHNICAL:
                teamList = soloTechList;
                break;

            case SOLO_FREE:
                teamList = soloFreeList;
                break;

            case DUO:
                teamList = duoList;
                break;

            case DUO_TECHNICAL:
                teamList = duoTechList;
                break;

            case DUO_FREE:
                teamList = duoFreeList;
                break;

            case COMBO:
                teamList = comboList;
                break;

            default:
                teamList = figureList;
                LOGGER.error("Team type inconnu!");
                break;
        }

        for (Team team : teamList) {
            Collection<Athlete> athletes = team.getAthletes();

            for (Athlete athlete : athletes) {
                LOGGER.info(index + " Athlete name: " + athlete.getName() + " subs "
                        + " Club " + clubList.get((int) team.getClubId()).getName() + " coach: " +
                        team.getCoaches());
            }

            LOGGER.info("nb susbstitute = " + team.getSubstitutes().size());

            ++index;
        }

        return teamList;
    }

    public void createFile() throws IOException {
        int stepRow = 13;

        FileOutputStream fileOut;

        try {
            InputStream in = new FileInputStream("C:/Users/magirard/Documents/Eliane/template.xls");

            Workbook template = new HSSFWorkbook(in);

            Sheet sheet = template.getSheet("FORMATION COMBO");

            LOGGER.info("SHEET NAME " + sheet.getSheetName());

            Iterator<Team> itr = comboList.iterator();

            int inxTeam = 0;
            while (itr.hasNext()) {
                Team team = itr.next();

                int i = 1 + inxTeam * stepRow;

                Collection<Athlete> athletes = team.getAthletes();
                int athletesCount = athletes.size();

                for (Athlete athlete : athletes) {
                    Cell cell = sheet.getRow(i).getCell(1);
                    cell.setCellValue(athlete.getName());

                    cell = sheet.getRow(i).getCell(2);
                    cell.setCellValue(clubList.get((int) team.getClubId()).getName());

                    cell = sheet.getRow(i).getCell(4);
                    cell.setCellValue(team.getAgeSum() / athletesCount);

                    cell = sheet.getRow(i).getCell(5);
                    cell.setCellValue(team.getName());


                    ++i;
                }

                ++inxTeam;


                //athleteList.get((int) team.getFirstMemberId()).getName();
                //clubList.get((int) team.getClubId()).getName();
            }

            OutputStream out = new FileOutputStream("C:/Users/magirard/Documents/Eliane/template.xls");
            template.write(out);
            out.close();


        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public List<Athlete> getAthleteList() {
        return athleteList;
    }


}
